package bancosys.tec.persist.audit.domain;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Comment;
import jmine.tec.persist.annotation.Constraint;
import jmine.tec.persist.annotation.DiscriminatorComment;
import jmine.tec.persist.annotation.Index;
import jmine.tec.persist.schema.api.IndexOrder;

import org.hibernate.annotations.ForeignKey;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.bussobj.PersistableBusinessObject;

/**
 * @created 03/10/2007
 * @author Gustavo Almeida
 */
@Entity
@Table(name = "AUDIT_PROPERTY")
@Alias("AUDPRO")
@SequenceGenerator(name = "SEQ_AUDPRO", sequenceName = "SEQ_AUDPRO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TP_PROPERTY", discriminatorType = DiscriminatorType.INTEGER)
@Constraint(suffix = "0")
@Comment(table = "AUDIT_PROPERTY", column = "TP_PROPERTY", value = "TIPO DA PROPRIEDADE AUDITADA.")
@DiscriminatorValue("1")
@DiscriminatorComment("PROPRIEDADE COM VALOR NAO AUDITADO")
@Documentation("ARMAZENA AS PROPRIEDADES INCLUIDAS/MODIFICADAS DE CADA ENTIDADE NO PROCESSO DE AUDITORIA, PARA CADA VERSAO DA ENTIDADE.")
public class AuditProperty extends PersistableBusinessObject implements Comparable<AuditProperty> {
    protected static final int MAX_VARCHAR_LEN = 255;

    private Long id;

    private String xpath;

    private String name;

    private AuditVersion version;

    /**
     * Devolve o id de persistência dessa property.
     * 
     * @return o id de persistência dessa property.
     */
    @Id
    @Column(name = "COD_AUDIT_PROPERTY")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_AUDPRO")
    @Documentation("CODIGO DA PROPRIEDADE AUDITADA.")
    public Long getId() {
        return this.id;
    }

    /**
     * Define o id de persistência dessa property.
     * 
     * @param id id de persistência dessa property.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Devolve o xpath da propriedade.
     * 
     * @return o xpath da propriedade.
     */
    @Column(name = "XPATH", nullable = false, length = MAX_VARCHAR_LEN)
    @Documentation("CAMINHO DA PROPRIEDADE AUDITADA.")
    public String getXpath() {
        return this.xpath;
    }

    /**
     * Compara duas properties pelo valor do xpath.
     * 
     * @param o property a ser comparada com essa.
     * @return -1 se essa property for menor que <code>o</code>, 1 se for maior e 0 se for igual
     * @see Comparable
     */
    public int compareTo(AuditProperty o) {
        if (o == null) {
            return 1;
        }

        if (this.getXpath() == null) {
            if (o.getXpath() == null) {
                return 0;
            }
            return -1;
        }

        if (o.getXpath() == null) {
            return 1;
        }

        return this.getXpath().compareTo(o.getXpath());
    }

    /**
     * Define o xpath.
     * 
     * @param xpath O xpath a ser definido.
     */
    public void setXpath(String xpath) {
        this.xpath = xpath;
    }

    /**
     * Devolve o version.
     * 
     * @return o version.
     */
    @ManyToOne
    @ForeignKey(name = "FK_AUDVER_AUDPRO")
    @JoinColumn(name = "COD_AUDIT_VERSION")
    @Documentation("CODIGO DA PROPRIEDADE AUDITADA.")
    @Index(suffix = "0", orders = IndexOrder.ASC)
    public AuditVersion getVersion() {
        return this.version;
    }

    /**
     * Define o version.
     * 
     * @param version O version a ser definido.
     */
    public void setVersion(AuditVersion version) {
        this.version = version;
    }

    /**
     * Devolve o nome da propriedade.
     * 
     * @return o nome da propriedade.
     */
    @Column(name = "NAME", nullable = true, length = MAX_VARCHAR_LEN)
    @Documentation("NOME DA PROPRIEDADE AUDITADA.")
    public String getName() {
        return this.name;
    }

    /**
     * Define o name.
     * 
     * @param name O name a ser definido.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Devolve a representação string de uma <code>Property</code>.
     * 
     * @return a representação string de uma <code>Property</code>.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(this.xpath);
        sb.append(" ( ").append(this.name).append(")");
        return sb.toString();
    }

    /**
     * Compara essa instância com uma outra.
     * 
     * @param obj instância a ser comparada com essa.
     * @return <code>true</code> caso as duas instâncias sejam iguais, <code>false</code> caso contrário.
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!this.getClass().equals(obj.getClass())) {
            return false;
        }
        AuditProperty other = (AuditProperty) obj;

        if (this.getXpath() == null) {
            return other.getXpath() == null;
        }

        return this.getXpath().equals(((AuditProperty) obj).getXpath());
    }

    /**
     * Devolve o hascode dessa instância.
     * 
     * @return o hascode dessa instância.
     */
    @Override
    public int hashCode() {
        if (this.getXpath() == null) {
            return 0;
        }
        return this.getXpath().hashCode();
    }
}
